<?php

class CAccount extends CCoreLabsWebMailAccount
{
	const ACCOUNT_HASH_CHECK_PREFIX = 'acp';
	const ACCOUNT_HASH_CHECK_KEY = 'zzz';
	const ACCOUNT_HASH_DELIMITER = "\x0";

	/**
	 * @return array
	 */
	private static function _map()
	{
		return array(
			'q' => 'iIncMailProtocol',
			'r' => 'sIncHost',
			't' => 'iIncPort',
			'y' => 'sIncLogin',
			'u' => 'sIncPassword'
		);
	}

	/**
	 * @param string $sEncodedHash
	 * @return CAccount
	 */
	public static function CreateAccountFromHash($sEncodedHash)
	{
		$sDecodedHash = self::_decodeAccountHash($sEncodedHash);
		$aDecodedHashParts = explode(self::ACCOUNT_HASH_DELIMITER, $sDecodedHash);

		$aParts = array();
		foreach ($aDecodedHashParts as $sHashPart)
		{
			$aItemps = explode('=', $sHashPart, 2);
			if (2 === count($aItemps))
			{
				$aParts[$aItemps[0]] = $aItemps[1];
			}
		}

		if (self::_checkMapArray($aParts))
		{
			$oAccount = new CAccount((int) $aParts['q'], $aParts['r'], (int) $aParts['t'], $aParts['y'], $aParts['u']);

			return $oAccount;
		}
		
		return null;
	}

	/**
	 * @return string
	 */
	public function GetEncodedHash()
	{
		$aEncodeAccountArray = array();
		$aMap = self::_map();
		foreach ($aMap as $sMapKey => $sMapItemValue)
		{
			$aEncodeAccountArray[$sMapKey] = $this->{$sMapItemValue};
		}

		$aEncodeAccountArray[self::ACCOUNT_HASH_CHECK_KEY] = self::ACCOUNT_HASH_CHECK_PREFIX;
		$aEncodeAccountArray = $this->_shuffleAssoc($aEncodeAccountArray);

		$aNewAccountArray = '';
		foreach ($aEncodeAccountArray as $sMapKey => $MapItemValue)
		{
			$aNewAccountArray[] = $sMapKey .'='.$MapItemValue;
		}

		return $this->_encodeAccountHash(implode(self::ACCOUNT_HASH_DELIMITER, $aNewAccountArray));
	}

	/**
	 * @param array $aAccountsParts
	 * @return bool
	 */
	private static function _checkMapArray($aAccountsParts)
	{
		$aMap = self::_map();
		foreach ($aMap as $sKey => $sValue)
		{
			if (!isset($aAccountsParts[$sKey]))
			{
				return false;
			}
		}
		return true;
	}

	/**
	 * @param $aIncArray $aIncArray
	 * @return $aIncArray
	 */
	private function _shuffleAssoc($aIncArray)
	{
		$aKeys = array_keys($aIncArray);

		shuffle($aKeys);

		$aOutArray = array();
		foreach ($aKeys as $sKey)
		{
			$aOutArray[$sKey] = $aIncArray[$sKey];
		}

		return $aOutArray;
	}

	/**
	 * @param string $sEncodedHash
	 * @return string
	 */
	private static function _decodeAccountHash($sEncodedHash)
	{
		include_once WEBMAIL_APP_ROOT.'libs/xxtea.php';
		return xxtea_decrypt(base64_decode($sEncodedHash), self::_getKey());
	}

	/**
	 * @param string $sDecodedHash
	 * @return string
	 */
	private static function _encodeAccountHash($sDecodedHash)
	{
		include_once WEBMAIL_APP_ROOT.'libs/xxtea.php';
		return base64_encode(xxtea_encrypt($sDecodedHash, self::_getKey()));
	}

	/**
	 * @staticvar string $sKey
	 * @return string
	 */
	private static function _getKey()
	{
		static $sKey = null;
		if (null === $sKey)
		{
			$sKey = include WEBMAIL_APP_ROOT.'data/key.php';
		}
		return $sKey;
	}
}